using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.IO;
using System.Windows.Forms;
using System.Reflection;
using CreamX.Framework.Game;

using CreamX.Framework.Game.GameEngine;
using CreamX.Framework.SceneGraph;
using CreamX.Framework.Attributes;


namespace CreamXStudio.Classes
{
    public class CreamXProjectSettings
    {
        [XmlIgnore()]
        public Dictionary<string, Assembly> AttributeInfo= new Dictionary<string, Assembly>();
        [XmlIgnore()]
        public Dictionary<string, Type> CreamXComponents = new Dictionary<string, Type>();
        public static CreamXProjectSettings Load(string filename)
        {
            try
            {
                
                XmlSerializer __ser = new XmlSerializer(typeof(CreamXProjectSettings));
                Stream __stream = File.Open(filename, FileMode.Open);
                CreamXProjectSettings __proj = (CreamXProjectSettings)__ser.Deserialize(__stream);
                __proj.FileName=filename;
                __proj.RootDIR = Path.GetDirectoryName(filename)+"\\";
                
                __proj.LoadAssemblies(__proj.RootDIR+@"bin\x86\Debug\");

                return __proj;
            }
            catch (UnauthorizedAccessException)
            {
                MessageBox.Show("Access Denied to file : " + filename);
                return null;
            }
            catch (Exception err)
            {
                CreamXErrorHandler.LogError(err);
                return null;
            }
        }
        public CreamXProjectSettings()
        { }
        private string _fileName;
        [XmlIgnore()]
	    public string FileName
	    {
		    get { return _fileName;}
		    set { _fileName = value;}
	    }
        
        [XmlIgnore()]
        public string RootDIR = "";

        private string _projectName;

        public string ProjectName
        {
            get { return _projectName; }
            set { _projectName = value; }
        }
        private string _contentRoot;

        public string ContentRoot
        {
            get { return _contentRoot; }
            set { _contentRoot = value; }
        }
        private string _outputPath;

        public string OutputPath
        {
            get { return _outputPath; }
            set { _outputPath = value; }
        }
        private string _sceneData;

        public string SceneDataPath
        {
            get { return _sceneData; }
            set { _sceneData = value; }
        }

        private string _vsProjFile;

        public string VisualStudioProjectFile
        {
            get { return _vsProjFile; }
            set { _vsProjFile = value; }
        }
        bool AssemblyAlreadyAdded(Assembly asm)
        {
            foreach (Assembly _asm in Assemblies)
            {
                if (_asm.FullName == asm.FullName)
                    return true;
            }
            return false;
        }
        [XmlIgnore()]
        public List<Assembly> Assemblies = new List<Assembly>();
        public void LoadAssemblies(string rootpath)
        {
            foreach (Assembly asm in SessionData.Instance.DefaultAssemblies)
            {
                if (asm!= null && HasCustomComponent(asm))
                {
                    if (!AssemblyAlreadyAdded(asm))
                    {
                        Assemblies.Add(asm);
                        AddAttributeInfo(asm);
                    }
                }
            }
            string __rootPath = rootpath; 
            foreach (string __fil in Directory.GetFiles(__rootPath))
            {
                try
                {
                    string ext = Path.GetExtension(__fil);
                    if (Path.GetExtension(__fil) != ".exe" && Path.GetExtension(__fil) != ".dll")
                        continue;
                    Assembly __asm = Assembly.LoadFile(__fil);
                    if (__asm != null && HasCustomComponent(__asm))
                    {
                        if (!AssemblyAlreadyAdded(__asm))
                        {
                            Assemblies.Add(__asm);
                            AddAttributeInfo(__asm);
                        }
                    }
                }
                catch (Exception err)
                {
                    CreamXErrorHandler.LogError(err);
                }
            }

            __rootPath = OutputPath;
        }

        private void AddAttributeInfo(Assembly __asm)
        {
            foreach (Type t in __asm.GetTypes())
            {
                if (t.IsDefined(typeof(CreamXComponentAttribute), true))
                {
                    // if (!SessionData.Instance.ProjectSettings.Assemblies.Contains(__asm))
                    //    SessionData.Instance.ProjectSettings.Assemblies.Add(__asm);
                    object[] __att = t.GetCustomAttributes(typeof(CreamXComponentAttribute), true);
                    if (__att.Length > 0)
                    {
                        CreamXComponentAttribute __c = __att[0] as CreamXComponentAttribute;
                        if (!AttributeInfo.ContainsKey(__c.FriendlyName))
                        {
                            AttributeInfo.Add(__c.FriendlyName, __asm);
                            this.CreamXComponents.Add(__c.FriendlyName, t);
                        }
                    }
                }
            }
        }

        private bool HasCustomComponent(Assembly __asm)
        {
            foreach (Type __type in __asm.GetTypes())
            {
                if (__type.Name.Contains("Component"))
                    Console.Write("");
                //object[] __attribs = __type.GetCustomAttributes(typeof(CreamX.Framework.Game.Attributes.CreamXComponentAttribute), true);
                object[] __attribs = __type.GetCustomAttributes(true);
                if (__attribs.Length > 0)
                {
                    foreach (object var in __attribs)
                    {
                        if (var.GetType().Name == typeof(CreamXComponentAttribute).Name)
                            return true;
                    }
                    
                }
                
            }
            return false;
        }

        internal string GetScenePath()
        {
            return Path.GetDirectoryName(RootDIR +SceneDataPath); 
        }

        internal void Save()
        {
            Stream strm = File.Open(FileName,FileMode.Open,FileAccess.ReadWrite);
            XmlSerializer __ser = new XmlSerializer(typeof(CreamXProjectSettings));
            __ser.Serialize(strm,this);
            strm.Close();

        }
    }

    public class CreamXSceneSettings
    {
        public CreamXProjectSettings ProjectParent=null;
        public string Filename;
        public CreamXSceneData SceneData;

        public static CreamXSceneSettings LoadSceneData(string filename,CreamXProjectSettings project)
        {
            try
            {

                CreamXSceneSettings __scene = new CreamXSceneSettings();
                __scene.ProjectParent = project;
                __scene.Filename = filename;
                
                __scene.SceneData = CreamXGameEngine.LoadSceneStatic(filename, project.Assemblies);
                return __scene;
            }
            catch (Exception err)
            {
                CreamXErrorHandler.LogError(err);
                return null;
            }
        }
    }
}
